package nl.weeaboo.sh.objects;

import static nl.weeaboo.sh.level.Level.toTileCoord;

import java.awt.Rectangle;
import java.util.Random;

import nl.weeaboo.game.input.UserInput;
import nl.weeaboo.sh.Game;
import nl.weeaboo.sh.level.ActiveTiles;
import nl.weeaboo.sh.level.Level;
import nl.weeaboo.sh.level.Tile;
import nl.weeaboo.sh.model.DamageRect;
import nl.weeaboo.sh.view.CharaImage;
import nl.weeaboo.sh.view.anim.Animation;
import nl.weeaboo.sh.view.anim.AnimationFrame;

public abstract class Enemy extends Monster {

	protected static Random random = new Random();
	
	protected Animation anim;
	protected Animation a_walk;
	protected Animation a_attack;
	
	protected int frame;
	protected int attackFrame;
	protected boolean dontWalkOffLedges;

	public Enemy(Game game, Level level, CharaImage image) {
		super(game, level, image);
		
		dontWalkOffLedges = true;
	}
	
	//Functions
	public void destroy() {
		super.destroy();
		
		level.addEffect(new Explosion(game, level, image, x, y, rotation, dir==-1, false));
	}
	
	public void onHitWall(int d, boolean wallJumpable) {
		super.onHitWall(d, wallJumpable);
		
		if (dir == d) {
			dir = -d;
		}
		speedX = dir * 2.0f;
	}

	public boolean onHit(Sprite hitter, int damage, Rectangle hitArea, DamageRect dr) {
		if (super.onHit(hitter, damage, hitArea, dr)) {
			float knockbackX = (dr.knockbackX * Math.signum(x - hitter.getX())) / knockbackInertia;
			float knockbackY = dr.knockbackY / knockbackInertia;
			if (Math.abs(knockbackX) >= 1f || Math.abs(knockbackY) >= 1f) {
				setSpeed(knockbackX, knockbackY);
			}			
			
			attackFrame = frame = 0;			
			return true;
		}
		return false;
	}
	
	protected abstract int recalculateAttackFrame();
	protected abstract void attack();
	
	public void update(UserInput input, float dt) {		
		anim.request(a_walk);
		if (frame >= attackFrame) {
			attackFrame = recalculateAttackFrame();
			
			if (frame > 0) {
				frame = 0;
				anim = anim.next(a_attack);
				attack();
			}
		}
		
		anim = anim.update(1);
		AnimationFrame currentFrame = anim.getCurrentFrame();
		if (currentFrame != null) {
			setImage((CharaImage)currentFrame.getImage());
		}		
		
		if (grounded) { //Friction
			if (Math.abs(speedX) > 2.0f) {
				speedX *= 1.0f - groundFriction;
			}
			if (dir == 1  && speedX < 2.0f)  speedX += 0.1f;
			if (dir == -1 && speedX > -2.0f) speedX -= 0.1f;
		}
		
		frame++;

		if (dontWalkOffLedges && grounded && speedY >= 0 && anim != a_attack) { //Don't walk off ledges
			ActiveTiles at = level.getActiveTiles();
			Rectangle lhb = getLevelHitBox();
			int atx = at.getX();
			int aty = at.getY();
			int nx = (int)(x + Math.ceil(speedX));
			int ny = (int)(y + Math.ceil(speedY));
			int ty = toTileCoord(ny + lhb.y + lhb.height);
			
			Tile tile;
			tile = at.getTile(toTileCoord(nx + lhb.x)-atx, ty-aty);
			if (tile == null || !tile.isSolidV(1)) {
				dir = 1; speedX = dir * 2;
			}
			tile = at.getTile(toTileCoord(nx + lhb.x + lhb.width)-atx, ty-aty);
			if (tile == null || !tile.isSolidV(1)) {
				dir = -1; speedX = dir * 2;
			}
		}
		
		super.update(input, dt);
	}

	//Getters
	
	//Setters
	
}
